package top.ybq87;

/**
 * 自增变量的测试
 * @author ly
 * @blog http://www.ybq87.top
 * @github https://github.com/Lingouzi
 * @email 664162337@qq.com
 * @wechat ly19870316 / 公众号：林子曰
 * @date 2020/4/16
 */
public class MainClass {

    public static void main(String[] args) {
        // 注意方法编译之后，产生了 4 个局部变量【LOCALVARIABLE】，args，i，j，k，序号分别为 0，1，2，3
        // 我们用数组的概念来代替下，方便理解，arr[0] = args,arr[1] = i,arr[2] = j,arr[3] = k, 当然实际情况更复杂点
        // LOAD、STORE 指令后面的参数，第一个参数一般是局部变量的序号，也就是数组角标
        /*
        查看指令
        ICONST_1  ：将 int 型的值 1 推送至栈顶，操作数栈 = 1
        ISTORE 1  ：将栈顶 int 型数值存入指定序号的局部变量，序号为 1 的局部变量为 i，所以 i = 1，操作数栈全部弹出
         */
        int i = 1;
        /*
        查看指令
        ILOAD 1   ：将指定的 int 型的序号为 1 的局部变量的值，推送至栈顶，也就是将 i 的值压栈，操作数栈：1
        // iinc 用于实现局部变量的自增操作。在所有字节码指令中，只有该指令可直接用于操作局部变量。
        // 也就是说，这个命令不会改变操作数栈！
        IINC 1 1  ：int 型的序号为 1 的局部变量，增加指定值 1， 所以 i = 1 + 1，但是操作数栈：1
        ISTORE 1  ：将栈顶 int 型数值存入指定序号的局部变量；序号为 1 的变量为 i，所以将操作数栈顶针，出栈给 i = 1，操作数栈空
         */
        i = i++;
        /*
        ILOAD 1   ：加载序号为 1 的局部变量的值到操作数栈：1
        IINC 1 1  ：局部变量序号为 1 的值+1，也就是局部变量 i 自己+1，i = 2，但是操作数栈还是 1
        ISTORE 2  ：将栈顶的元素弹栈，将值给需要为 2 的局部变量，也就是 j。j = 1，此时 i 已经是 2 了
         */
        int j = i++;
        /*
        查看指令：
        ILOAD 1   ：序号 = 1 的局部变量值压栈，操作数栈 = 2
        IINC 1 1  ：序号 = 1 的局部变量自加，i 之前已经是 2了，再自加 = 3，操作数栈不变 = 2
        ILOAD 1   ：将 序号 = 1 的局部变量又压栈，也就是 i = 3，将 3 压栈，操作数栈：3，2
        ILOAD 1   ：再压栈，i = 3，操作数栈：3，3，2
        IINC 1 1  ：i++，此时 i = 4，此操作不影响操作数栈，所以操作数栈：3，3，2
        IMUL      ：将栈顶两int型数值相乘并将结果压入栈顶，前 2 个值为 3*3 = 9，将 9 压栈，操作数栈为：9，2
        IADD      ：将栈顶两int型数值相加并将结果压入栈顶，9 + 2，压栈，操作数栈：11
        ISTORE 3  ：弹栈，赋值给需要为 3 的局部变量，k = 11
         */
        int k = i + ++i * i++;
        // 猜测打印结果
        System.out.println(i);
        System.out.println(j);
        System.out.println(k);
    }
}
